#include "ShaderManager.h"
#include "s3e.h"
#include "memory"

ShaderManager::ShaderManager(void)
{
}


ShaderManager::~ShaderManager(void)
{
}

GLuint ShaderManager::CreateShader(GLenum type, const char* pSource)
{
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &pSource, NULL);
    glCompileShader(shader);
    //printShaderInfoLog(shader);
    return shader;
}

bool ShaderManager::CheckShader(GLint shader)
{
	GLint length;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
    if (length)
    {
        //char* buffer = (char*)malloc( sizeof(char) * length ) ;
       // glGetShaderInfoLog(shader, length, NULL, buffer);
        //printf("%s", buffer);
        //free( buffer ) ;
        GLint success;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if(success != GL_TRUE)
		{
            return false;
        }
    }

	return true;
}

bool ShaderManager::CompileShaders(GLuint *shaderProg, const char *vertexSrc, const char *fragmentSrc)
{
    *shaderProg = glCreateProgram();

    GLuint vertexShader = CreateShader(GL_VERTEX_SHADER, vertexSrc);
	if(CheckShader(vertexShader) == false)
	{
		return false;
	}

    GLuint fragmentShader = CreateShader(GL_FRAGMENT_SHADER, fragmentSrc);
	if(CheckShader(fragmentShader) == false)
	{
		return false;
	}

    glAttachShader(*shaderProg, vertexShader);
    glAttachShader(*shaderProg, fragmentShader);

    glLinkProgram(*shaderProg);

    glUseProgram(*shaderProg);

	return true;
}

bool ShaderManager::Initialize()
{
	s3eFile *file = 0;
	int size;
	char *vertBuf;
	char *fragBuf;

	/// MAIN SHADER ==============================================================
	// read vertex shader file
	file = ::s3eFileOpen("MainVertexShader.txt", "r");
	size = ::s3eFileGetSize(file);

	vertBuf = new char[size];
	memset(vertBuf, 0, size);

	::s3eFileRead(vertBuf, sizeof(char), size, file);
	::s3eFileClose(file);

	// read fragment shader file
	file = ::s3eFileOpen("MainFragmentShader.txt", "r");
	size = ::s3eFileGetSize(file);

	fragBuf = new char[size];
	memset(fragBuf, 0, size);

	::s3eFileRead(fragBuf, sizeof(char), size, file);
	::s3eFileClose(file);

	if(CompileShaders(&m_mainShader, vertBuf, fragBuf) == false)
	{
		delete [] vertBuf;
		delete [] fragBuf;
		return false;
	}

	delete [] vertBuf;
	delete [] fragBuf;


	// GET UNIFORM LOCATIONS
	m_mainShaderMVP = glGetUniformLocation(m_mainShader, "mvpMatrix");

	// ==========================================================================
	//throw("failed to initialize main shader");

	return true;
}

void ShaderManager::UseMainShader()
{
	::glUseProgram(this->m_mainShader);
}